<h2>事件绑定(ms-on-*)</h2>
<p>之前的章节许多示例代码也或多或少地展示了如何使用ms-click来绑定事件了。能直接在模板上绑定是事件，这也是静态模板与动态绑定的一大区别。ms-click不是简单的onclick的别名，它在内部屏蔽了浏览器的差异，并且对许多浏览器暂时不支持的事件做了兼容处理。</p>

<p>总的来说，事件绑定是使用ms-on-☆绑定来实现，但avalon也提供了许多快捷方式，让用户能直接以ms-eventName调用那些常用事件，如下</p>

<blockquote>
    <p>animationend、  blur、  change、  input、 click、 dblclick、 focus、 keydown、 keypress、 keyup、 mousedown、 mouseenter、 mouseleave、 mousemove、 mouseout、 mouseover、 mouseup、 scan、 scroll、 submit</p>
</blockquote>

<p>事件绑定的属性值的格式，必须是函数名或函数名后＋小括号(ms-on-click="aaa.fn"是不被允许的)。
    小括号不是必须的。它用于添加参数，并且有一个特殊的<code>$event</code>参数，指向事件对象。如果不写小括号，默认第一个参数就是事件对象。</p>
<div class="alert alert-danger" role="alert">
    <p>注意:ms-duplex与ms-input不能用在同一元素上。</p>
</div>
<p>IE6-8下，事件对象的许多属性与方法与标准浏览器不一样，不过放心，avalon已经帮你修正了。详见下面源码：</p>
<xmp class="javascript">
    function fixEvent(event) {
    var ret = {}
    for (var i in event) {
    ret[i] = event[i]
    }
    var target = ret.target = event.srcElement
    if (event.type.indexOf("key") === 0) {
    ret.which = event.charCode != null ? event.charCode : event.keyCode
    } else if (/mouse|click/.test(event.type)) {
    var doc = target.ownerDocument || DOC
    var box = doc.compatMode === "BackCompat" ? doc.body : doc.documentElement
    ret.pageX = event.clientX + (box.scrollLeft >> 0) - (box.clientLeft >> 0)
    ret.pageY = event.clientY + (box.scrollTop >> 0) - (box.clientTop >> 0)
    ret.wheelDeltaY = ret.wheelDelta
    ret.wheelDeltaX = 0
    }
    ret.timeStamp = new Date - 0
    ret.originalEvent = event
    ret.preventDefault = function() { //阻止默认行为
    event.returnValue = false
    }
    ret.stopPropagation = function() { //阻止事件在DOM树中的传播
    event.cancelBubble = true
    }
    return ret
    }
</xmp>
<p>avalon的事件绑定支持<code>多投事件机制</code>（同一个元素可以绑定N个同种事件，如ms-click=fn, ms-click-1=fn2, ms-click-2=fn3）</p>

<xmp class="html">
    <!DOCTYPE HTML>
    <html>
        <head>
            <title>ms-on</title>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
            <script src="avalon.js" ></script>
            <script>
                var model = avalon.define({
                    $id: "test",
                    firstName: "司徒",
                    array: ["aaa", "bbb", "ccc"],
                    argsClick: function (e, a, b) {
                        alert([].slice.call(arguments).join(" "))
                    },
                    loopClick: function (a, e) {
                        alert(a + "  " + e.type)
                    },
                    status: "",
                    callback: function (e) {
                        model.status = e.type
                    },
                    field: "",
                    check: function (e) {
                        model.field = this.value + "  " + e.type
                    },
                    submit: function () {
                        var data = model.$model
                        if (window.JSON) {
                            setTimeout(function () {
                                alert(JSON.stringify(data))
                            })
                        }
                    }
                })

            </script>
        </head>
        <body>
            <fieldset ms-controller="test">
                <legend>有关事件回调传参</legend>
                <div ms-mouseenter="callback" ms-mouseleave="callback">{{status}}<br/>
                    <input ms-on-input="check"/>{{field}}
                </div>
                <div ms-click="argsClick($event, 100, firstName)">点我</div>
                <div ms-each-el="array" >
                    <p ms-click="loopClick(el, $event)">{{el}}</p>
                </div>
                <button ms-click="submit">点我</button>
            </fieldset>
        </body>
    </html>
</code></xmp>

<p><img src="../../assets/css/directives/on/1409902096503-click.gif"  /></p>

<xmp class="html"><!DOCTYPE HTML>
    <html>
        <head>
            <title>ms-on</title>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
            <script src="avalon.js" ></script>
            <script>
                var count = 0
                var model = avalon.define({
                    $id: "multi-click",
                    str1: "1",
                    str2: "2",
                    str3: "3",
                    click0: function () {
                        model.str1 = "xxxxxxxxx" + (count++)
                    },
                    click1: function () {
                        model.str2 = "xxxxxxxxx" + (count++)
                    },
                    click2: function () {
                        model.str3 = "xxxxxxxxx" + (count++)
                    }
                })
            </script>
        </head>
        <body>
            <fieldset>
                <legend>一个元素绑定多个同种事件的回调</legend>
                <div ms-controller="multi-click">
                    <div ms-click="click0" ms-click-1="click1" ms-click-2="click2" >请点我</div>
                    <div>{{str1}}</div>
                    <div>{{str2}}</div>
                    <div>{{str3}}</div>
                </div>
            </fieldset>
        </body>
    </html>
</code></xmp>

<p><img src="../../assets/css/directives/on/1409902480576-click2.gif"  /></p>

<xmp class="html"><!DOCTYPE HTML>
    <html>
        <head>
            <title>ms-on</title>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
            <script src="avalon.js" ></script>
            <script>
                avalon.define({
                    $id: "xxx",
                    fn: function () {
                        console.log("11111111")
                    },
                    fn1: function () {
                        console.log("2222222")
                    },
                    fn2: function () {
                        console.log("3333333")
                    }
                })
            </script>
        </head>
        <body>
            <div ms-controller="xxx"
                 ms-on-mouseenter-3="fn"
                 ms-on-mouseenter-2="fn1"
                 ms-on-mouseenter-1="fn2"
                 style="width:100px;height:100px;background: red;"
                 >
            </div>
        </body>
    </html>
</code></xmp>

<p><img src="../../assets/css/directives/on/1409902782256-click3.gif" /></p>
<div class="alert alert-success" role="alert">
    <p>avalon已经对ms-mouseenter, ms-mouseleave进行修复，可以在<a href="http://bl.ocks.org/mbostock/5247027">这里</a>与<a href="http://stackoverflow.com/questions/6130737/mouseenter-without-jquery">这里</a>了解这两个事件。到chrome30时，所有浏览器都原生支持这两个事件。</p>
</div>
<xmp class="html"><!DOCTYPE html> <html>
        <head>
            <title>ms-mouseenter, ms-mouseleave</title>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
            <script src="avalon.js"></script>
            <script>
                avalon.define({
                    $id: "test",
                    fn1: function (e) {
                        console.log(e.type)
                        console.log(this)
                    },
                    fn2: function (e) {
                        console.log(e.type)
                        console.log(this)
                    }
                })
            </script>
        </head>

        <body ms-controller="test">
            <div ms-mouseenter="fn1" ms-mouseleave="fn2" style="background: red;width:200px;height: 200px;padding:20px;">
                <div style="background: blue;width:160px;height: 160px;margin:20px;"></div>
            </div>
        </body> </html>
</code></xmp>

<p><img src="../../assets/css/directives/on/1409903572570-click4.gif"  /></p>
<div class="alert alert-success" role="alert">
    <p>最后是mousewheel事件的修改，主要问题是出现firefox上，它死活也不愿意支持mousewheel，在avalon里是用DOMMouseScroll或wheel实现模拟的。我们在事件对象通过wheelDelta属性是否为正数判定它在向上滚动。</p>
</div>
<xmp class="html">
    <!DOCTYPE html>
    <html>
        <head>
            <title>ms-on-mousewheel</title>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
            <script src="avalon.js"></script>
            <script>
                var model = avalon.define({
                    $id: "test",
                    text: "",
                    callback: function (e) {
                        model.text = e.wheelDelta + "  " + e.type
                    }
                })

            </script>
        </head>

        <body ms-controller="test">
            <div ms-on-mousewheel="callback" id="aaa" style="background: red;width:200px;height: 200px;">
                {{text}}
            </div>
        </body>
    </html>
</code></xmp>

<p><img src="../../assets/css/directives/on/1409904002238-click5.gif" /></p>

<div class="bs-callout bs-callout-info" id="callout-alerts-dismiss-use-button">
    <h4>如何解除ms-on-*, ms-click等绑定的事件回调?</h4>
    <div>抱歉地告诉你，不能。不过我们可以用另一个折衷的方式达到相同的效果。</div>
</div>
<p>看一下面的例子：</p>
<xmp class="html">
    <!DOCTYPE html>
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
            <script src="avalon.js"></script>
            <script>
                var vm = avalon.define({
                    $id: "test",
                    fn: function () {
                        alert(1)
                    }
                })
                setTimeout(function () {
                    vm.fn = function () {
                        alert(2)
                    }
                }, 3000)
                setTimeout(function () {
                    vm.fn = function () {
                        alert(3)
                    }
                }, 6000)
            </script>
        </head>
        <body>
            <div ms-controller="test">
                <button type="button" ms-click="fn">点击</button>
            </div>
        </body>
    </html>
</xmp>
<p><img src="../../assets/css/directives/on/click6.gif"  /></p>
<p>换言之，你想解除某个事件，就直接将VM中对应的函数置换为<code>空函数</code>就行了！</p>
<p>此外avalon还对input，animationend事件进行修复，大家也可以直接用avalon.bind, avalon.fn.bind来绑定这些事件。但建议都用ms-on绑定来处理。</p>
